home *** CD-ROM | disk | FTP | other *** search
/ Aminet 43 / Aminet 43 (2001)(GTI - Schatztruhe)[!][Jun 2001].iso / Aminet / comm / mail / YAM22src.lha / YAM_MAf.c < prev    next >
C/C++ Source or Header  |  2000-11-03  |  23KB  |  698 lines

  1. /***************************************************************************
  2.  
  3.  YAM - Yet Another Mailer
  4.  Copyright (C) 2000  Marcel Beck <mbeck@yam.ch>
  5.  
  6.  This program is free software; you can redistribute it and/or modify
  7.  it under the terms of the GNU General Public License as published by
  8.  the Free Software Foundation; either version 2 of the License, or
  9.  (at your option) any later version.
  10.  
  11.  This program is distributed in the hope that it will be useful,
  12.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  GNU General Public License for more details.
  15.  
  16.  You should have received a copy of the GNU General Public License
  17.  along with this program; if not, write to the Free Software
  18.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20.  YAM Official Support Site :  http://www.yam.ch
  21.  YAM OpenSource project    :  http://sourceforge.net/projects/yamos/
  22.  
  23. ***************************************************************************/
  24.  
  25. #include "YAM.h"
  26. #include "YAM_rexx.h"
  27.  
  28. /***************************************************************************
  29.  Module: Main - Folder handling
  30. ***************************************************************************/
  31.  
  32. /*** Index Maintenance ***/
  33.  
  34. /// MA_PromptFolderPassword
  35. //  Asks user for folder password
  36. BOOL MA_PromptFolderPassword(struct Folder *fo, APTR win)
  37. {
  38.    char passwd[SIZE_PASSWORD], prompt[SIZE_LARGE];
  39.    struct User *user = US_GetCurrentUser();
  40.  
  41.    if (fo->Flags&FOFL_FREEXS) return TRUE;
  42.    if (!Stricmp(fo->Password, user->Password)) return TRUE;
  43.    sprintf(prompt, GetStr(MSG_MA_GetFolderPass), fo->Name);
  44.    do {
  45.       *passwd = 0;
  46.       if (!StringRequest(passwd, SIZE_PASSWORD, GetStr(MSG_Folder), prompt, GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), TRUE, win)) return FALSE;
  47.    } while (Stricmp(passwd, fo->Password));
  48.    return TRUE;
  49. }
  50. ///
  51. /// MA_ValidateStatus
  52. //  Avoids invalid status values
  53. void MA_ValidateStatus(struct Folder *folder)
  54. {
  55.    struct Mail *mail;
  56.  
  57.    for (mail = folder->Messages; mail; mail = mail->Next)
  58.       if (mail->Status == STATUS_NEW)
  59.          if (folder->Type == FT_OUTGOING) MA_SetMailStatus(mail, STATUS_WFS);
  60.          else if (folder->Type == FT_SENT) MA_SetMailStatus(mail, STATUS_SNT);
  61.          else if (C->UpdateNewMail) MA_SetMailStatus(mail, STATUS_UNR);
  62. }
  63. ///
  64. /// MA_IndexFileName
  65. //  Returns file name of folder index
  66. char *MA_IndexFileName(struct Folder *folder)
  67. {
  68.    static char buffer[SIZE_PATHFILE];
  69.    strcpy(buffer, GetFolderDir(folder));
  70.    AddPart(buffer, ".index", SIZE_PATHFILE);
  71.    return buffer;
  72. }
  73. ///
  74. /// MA_LoadIndex
  75. //  Loads a folder index from disk
  76. int MA_LoadIndex(struct Folder *folder, BOOL full)
  77. {
  78.    FILE *fh;
  79.    int indexloaded = 0;
  80.    char buf[SIZE_LARGE];
  81.  
  82.    if (fh = fopen(MA_IndexFileName(folder), "r"))
  83.    {
  84.       struct FIndex fi;
  85.       Busy(GetStr(MSG_BusyLoadingIndex), folder->Name, 0, 0);
  86.       fread(&fi, sizeof(struct FIndex), 1, fh);
  87.       if (fi.ID == MAKE_ID('Y','I','N','3'))
  88.       {
  89.          folder->Total = fi.Total; folder->New = fi.New; folder->Unread = fi.Unread; folder->Size = fi.Size;
  90.          indexloaded++;
  91.          if (full)
  92.          {
  93.             ClearMailList(folder, TRUE);
  94.             for (;;)
  95.             {
  96.                struct Mail mail;
  97.                struct ComprMail cmail;
  98.                clear(&mail, sizeof(struct Mail));               
  99.                if (fread(&cmail, sizeof(struct ComprMail), 1, fh) != 1) break;
  100.                fread(buf, 1, cmail.MoreBytes, fh);
  101.                strcpy(mail.Subject, GetNextLine(buf));
  102.                strcpy(mail.From.Address, GetNextLine(NULL));
  103.                strcpy(mail.From.RealName, GetNextLine(NULL));
  104.                strcpy(mail.To.Address, GetNextLine(NULL));
  105.                strcpy(mail.To.RealName, GetNextLine(NULL));
  106.                strcpy(mail.ReplyTo.Address, GetNextLine(NULL));
  107.                strcpy(mail.ReplyTo.RealName, GetNextLine(NULL));
  108.                mail.Folder = folder;
  109.                mail.Flags = (cmail.Flags&0x7ff);
  110.                strcpy(mail.MailFile, cmail.MailFile);
  111.                mail.Date = cmail.Date;
  112.                mail.Status = cmail.Status;
  113.                mail.Importance = cmail.Importance;
  114.                mail.cMsgID = cmail.cMsgID;
  115.                mail.cIRTMsgID = cmail.cIRTMsgID;
  116.                mail.Size = cmail.Size;
  117.                AddMailToList(&mail, folder);
  118.             }
  119.             indexloaded++;
  120.             folder->Flags &= ~FOFL_MODIFY;
  121.          }
  122.       }
  123.       BusyEnd;
  124.       fclose(fh);
  125.    }
  126.    return indexloaded;
  127. }
  128. ///
  129. /// MA_SaveIndex
  130. //  Saves a folder index to disk
  131. BOOL MA_SaveIndex(struct Folder *folder)
  132. {
  133.    struct Mail *mail;
  134.    FILE *fh;
  135.    struct ComprMail cmail;
  136.    char buf[SIZE_LARGE];
  137.    struct FIndex fi;
  138.  
  139.    if (!(fh = fopen(MA_IndexFileName(folder), "w"))) return FALSE;
  140.    Busy(GetStr(MSG_BusySavingIndex), folder->Name, 0, 0);
  141.    fi.ID = MAKE_ID('Y','I','N','3');
  142.    fi.Total = folder->Total; fi.New = folder->New; fi.Unread = folder->Unread; fi.Size = folder->Size;
  143.    fwrite(&fi, sizeof(struct FIndex), 1, fh);
  144.    for (mail = folder->Messages; mail; mail = mail->Next)
  145.    {
  146.       clear(&cmail, sizeof(struct ComprMail));
  147.       sprintf(buf, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
  148.          mail->Subject,
  149.          mail->From.Address, mail->From.RealName,
  150.          mail->To.Address, mail->To.RealName,
  151.          mail->ReplyTo.Address, mail->ReplyTo.RealName);
  152.       cmail.Flags = mail->Flags;
  153.       strcpy(cmail.MailFile, mail->MailFile);
  154.       cmail.Date = mail->Date;
  155.       cmail.Status = mail->Status;
  156.       cmail.Importance = mail->Importance;
  157.       cmail.cMsgID = mail->cMsgID;
  158.       cmail.cIRTMsgID = mail->cIRTMsgID;
  159.       cmail.Size = mail->Size;
  160.       cmail.MoreBytes = strlen(buf);
  161.       fwrite(&cmail, sizeof(struct ComprMail), 1, fh);
  162.       fwrite(buf, 1, cmail.MoreBytes, fh);
  163.    }
  164.    fclose(fh);
  165.    folder->Flags &= ~FOFL_MODIFY;
  166.    BusyEnd;
  167.    return TRUE;
  168. }
  169. ///
  170. /// MA_GetIndex
  171. //  Opens/unlocks a folder
  172. BOOL MA_GetIndex(struct Folder *folder)
  173. {
  174.    if (!folder) return FALSE;
  175.    if (folder->Type == FT_SEPARATOR) return FALSE;
  176.    if (folder->LoadedMode != 2)
  177.    {
  178.       if (*folder->Password && (folder->XPKType&1))
  179.          if (!MA_PromptFolderPassword(folder, G->MA->GUI.WI)) return FALSE;
  180.       if (!MA_LoadIndex(folder, TRUE))
  181.       {
  182.          MA_ScanMailBox(folder);
  183.          MA_SaveIndex(folder);
  184.       }
  185.       MA_ValidateStatus(folder);
  186.       folder->LoadedMode = 2;
  187.    }
  188.    return TRUE;
  189. }
  190. ///
  191. /// MA_ExpireIndex
  192. //  Invalidates a folder index
  193. void MA_ExpireIndex(struct Folder *folder)
  194. {
  195.    if (!(folder->Flags&FOFL_MODIFY)) DeleteFile(MA_IndexFileName(folder));
  196.    folder->Flags |= FOFL_MODIFY;
  197. }
  198. ///
  199. /// MA_UpdateIndexes
  200. //  Updates indices of all folders
  201. void MA_UpdateIndexes(BOOL initial)
  202. {
  203.    int i;
  204.    struct Folder **flist;
  205.  
  206.    if (flist = FO_CreateList())
  207.    {
  208.       for (i = 1; i <= (int)*flist; i++) if (flist[i]->Type != FT_SEPARATOR)
  209.          if (initial)
  210.          {
  211.             long dirdate = getft(GetFolderDir(flist[i]));
  212.             long inddate = getft(MA_IndexFileName(flist[i]));
  213.             if (dirdate > inddate+30 && inddate != -1)
  214.             {
  215.                DeleteFile(MA_IndexFileName(flist[i]));
  216.                MA_GetIndex(flist[i]);
  217.             }
  218.          }
  219.          else
  220.          {
  221.             if (flist[i]->LoadedMode == 2 && (flist[i]->Flags&FOFL_MODIFY)) MA_SaveIndex(flist[i]);
  222.          }
  223.       free(flist);
  224.    }
  225. }
  226. ///
  227. /// MA_FlushIndexes
  228. //  Removes loaded folder indices from memory and closes folders
  229. void MA_FlushIndexes(BOOL all)
  230. {
  231.    int i;
  232.    struct Folder *fo, **flist, *actfo = FO_GetCurrentFolder();
  233.  
  234.    if (flist = FO_CreateList())
  235.    {
  236.       for (i = 1; i <= (int)*flist; i++)
  237.       {
  238.          fo = flist[i];
  239.          if ((fo->Type == FT_SENT || fo->Type == FT_CUSTOM || fo->Type == FT_CUSTOMSENT) && fo != actfo  && fo->LoadedMode == 2 && (all || (fo->Flags&FOFL_FREEXS)))
  240.          {
  241.             if (fo->Flags&FOFL_MODIFY) MA_SaveIndex(fo);
  242.             ClearMailList(fo, FALSE);
  243.             fo->LoadedMode = 1;
  244.             fo->Flags &= ~FOFL_FREEXS;
  245.          }
  246.       }
  247.       free(flist);
  248.       DoMethod(G->MA->GUI.LV_FOLDERS, MUIM_NList_Redraw, MUIV_NList_Redraw_All);
  249.    }
  250. }
  251. SAVEDS void MA_FlushIndexFunc(void)
  252. {
  253.    MA_FlushIndexes(TRUE);
  254. }
  255. MakeHook(MA_FlushIndexHook, MA_FlushIndexFunc);
  256. ///
  257.  
  258. /*** Private functions ***/
  259. /// MA_ChangeFolder
  260. //  Changes to another folder
  261. void MA_ChangeFolder(struct Folder *folder)
  262. {
  263.    static struct Folder *lastfolder = NULL;
  264.    struct Folder *actfolder = FO_GetCurrentFolder();
  265.    BOOL folderopen = TRUE;
  266.    int i, pos = 0;
  267.  
  268.    if (actfolder != folder || actfolder != lastfolder)
  269.    {
  270.       struct MA_GUIData *gui = &G->MA->GUI;
  271.       set(gui->NL_MAILS, MUIA_ShortHelp, NULL);
  272.       if (lastfolder) lastfolder->LastActive = GetMUI(gui->NL_MAILS, MUIA_NList_Active);
  273.       if (folder) nnset(gui->NL_FOLDERS, MUIA_NList_Active, FO_GetFolderPosition(folder));
  274.       else folder = actfolder;
  275.       if (folder->Type == FT_SEPARATOR) folderopen = FALSE;
  276.       else if (!MA_GetIndex(folder)) folderopen = FALSE;
  277.       if (folderopen)
  278.       {
  279.          MA_SetSortFlag();
  280.          DisplayMailList(folder, gui->NL_MAILS);
  281.          DisplayStatistics(folder);
  282.          if (C->JumpToNewMsg) for (i = 0; ; i++)
  283.          {
  284.             struct Mail *mail;
  285.             DoMethod(gui->NL_MAILS, MUIM_NList_GetEntry, i, &mail);
  286.             if (!mail) break;
  287.             if (mail->Status == STATUS_NEW || mail->Status == STATUS_UNR) { pos = i; break; }
  288.          }
  289.          set(gui->NL_MAILS, MUIA_NList_Active, pos);
  290.       }
  291.       set(gui->LV_MAILS, MUIA_Disabled, !folderopen);
  292.       lastfolder = folder;
  293.    }
  294. }
  295. SAVEDS void MA_ChangeFolderFunc(void)
  296. {
  297.    struct Folder *folder = FO_GetCurrentFolder();
  298.    if (folder) MA_ChangeFolder(folder);
  299. }
  300. MakeHook(MA_ChangeFolderHook, MA_ChangeFolderFunc);
  301. ///
  302.  
  303. /*** Mail header scanning ***/
  304. /// MA_NewMailFile
  305. //  Returns an unique name for a new mail file
  306. char *MA_NewMailFile(struct Folder *folder, char *mailfile, int daynumber)
  307. {
  308.    static char buffer[SIZE_PATHFILE];
  309.    char mfile[SIZE_MFILE];
  310.    struct Mail *mail;
  311.    int cnt, mcnt = 0;
  312.    
  313.    if (!mailfile) mailfile = mfile;
  314.    if (!daynumber) { struct DateStamp ds; DateStamp(&ds); daynumber = ds.ds_Days; }
  315.    MA_GetIndex(folder);
  316.    for (mail = folder->Messages; mail; mail = mail->Next)
  317.       if (atoi(mail->MailFile) == daynumber)
  318.          if ((cnt = atoi(&(mail->MailFile)[6])) > mcnt) mcnt = cnt;
  319.    do {
  320.       sprintf(mailfile, "%05d.%03d", daynumber, ++mcnt);
  321.       strcpy(buffer, GetFolderDir(folder));
  322.       AddPart(buffer, mailfile, SIZE_PATHFILE);
  323.    } while (access(buffer,F_OK) == 0);
  324.    return buffer;
  325. }
  326. ///
  327. /// MA_DetectUUE
  328. //  Checks if message contains an uuencoded file
  329. BOOL MA_DetectUUE(FILE *fh)
  330. {
  331.    char *buffer;
  332.    BOOL found = FALSE;
  333.    int i;
  334.  
  335.    buffer = calloc(SIZE_LINE,1);
  336.    for (i = 0; GetLine(fh, buffer, SIZE_LINE) && !found && i < 30; i++)
  337.       if (!strncmp(buffer, "begin ", 6) && isdigit((int)buffer[6])) found = TRUE;
  338.    free(buffer);
  339.    return found;
  340. }
  341. ///
  342. /// MA_ReadHeader
  343. //  Reads header lines of a message into memory
  344. struct Data2D Header = { 0, 0, NULL };
  345.  
  346. BOOL MA_ReadHeader(FILE *fh)
  347. {
  348.    char *buffer, *ptr, *head;
  349.    BOOL success = FALSE;
  350.    char prevcharset[SIZE_DEFAULT];
  351.  
  352.    buffer = calloc(SIZE_LINE,1);
  353.    head   = calloc(SIZE_LINE,1);
  354.    FreeData2D(&Header);
  355.    while (GetLine(fh, buffer, SIZE_LARGE))
  356.    {
  357.       if (!buffer[0]) { success = TRUE; break; }
  358.       clear(head, SIZE_LINE);
  359.       strcpy(prevcharset, "us-ascii");
  360.       RE_ProcessHeader(prevcharset, buffer, TRUE, head);
  361.       if ((buffer[0] == ' ' || buffer[0] == '\t') && Header.Used)
  362.       {
  363.          for (ptr = head; *ptr && ISpace(*ptr); ptr++);
  364.          ptr = StrBufCat(Header.Data[Header.Used-1], ptr);
  365.       }
  366.       else                      
  367.          ptr = StrBufCpy(AllocData2D(&Header, SIZE_DEFAULT), head);
  368.       Header.Data[Header.Used-1] = ptr;
  369.    }
  370.    free(buffer); free(head);
  371.    return success;
  372. }  
  373. ///
  374. /// MA_FreeEMailStruct
  375. //  Frees an extended email structure
  376. void MA_FreeEMailStruct(struct ExtendedMail *email)
  377. {
  378.    if (email->SenderInfo) FreeStrBuf(email->SenderInfo);
  379.    if (email->Headers ) FreeStrBuf(email->Headers );
  380.    if (email->NoSTo)    free(email->STo);
  381.    if (email->NoCC )    free(email->CC );
  382.    if (email->NoBCC)    free(email->BCC);
  383.    clear(email, sizeof(struct ExtendedMail));
  384. }
  385. ///
  386. /// MA_GetRecipients
  387. //  Extracts recipients from a header field
  388. void MA_GetRecipients(char *h, struct Person **per, int *percnt)
  389. {
  390.    int cnt;
  391.    char *p = h, *next;
  392.    for (cnt = 0; *p;)
  393.    {
  394.       cnt++;
  395.       if (p = MyStrChr(p, ',')) p++; else break;
  396.    }
  397.    *percnt = cnt;
  398.    if (cnt)
  399.    {
  400.       *per = calloc(cnt, sizeof(struct Person));
  401.       for (cnt = 0, p = h; *p; cnt++)
  402.       {
  403.          if (next = MyStrChr(p, ',')) *next++ = 0;
  404.          ExtractAddress(p, (struct Person *)((ULONG)*per+cnt*sizeof(struct Person)));
  405.          if (!(p = next)) break;
  406.       }
  407.    }
  408. }
  409. ///
  410. /// MA_ExamineMail
  411. //  Parses the header lines of a message and fills email structure
  412. struct ExtendedMail *MA_ExamineMail(struct Folder *folder, char *file, char *statstr, BOOL deep)
  413. {
  414.    static struct ExtendedMail email;
  415.    static struct Person pe;
  416.    struct Mail *mail = (struct Mail *)&email;
  417.    char *p, fullfile[SIZE_PATHFILE];
  418.    int ok, i, j;
  419.    struct DateStamp *foundDate = NULL;
  420.    FILE *fh;
  421.  
  422.    clear(&email, sizeof(struct ExtendedMail));
  423.    stccpy(mail->MailFile, file, SIZE_MFILE);
  424.    email.DelSend = !C->SaveSent;
  425.    if (fh = fopen(GetMailFile(fullfile, folder, mail), "r"))
  426.    {
  427.       BOOL xpk = FALSE;
  428.       if (fgetc(fh) == 'X') if (fgetc(fh) == 'P') if (fgetc(fh) == 'K') xpk = TRUE;
  429.       if (xpk)
  430.       {
  431.          fclose(fh);
  432.          if (!StartUnpack(GetMailFile(NULL, folder, mail), fullfile, folder)) return NULL;
  433.          fh = fopen(fullfile, "r");
  434.       }
  435.       else rewind(fh);
  436.    }
  437.    if (fh)
  438.    {
  439.       MA_ReadHeader(fh);
  440.       if (MA_DetectUUE(fh)) mail->Flags |= MFLAG_MULTIPART;
  441.       fclose(fh);
  442.       for (ok=i=0; i < Header.Used; i++)
  443.       {
  444.          char *value, *field = Header.Data[i];
  445.          if (value = strchr(field, ':'))
  446.          {
  447.             *value++ = 0;
  448.             if (!stricmp(field, "from"))
  449.             {
  450.                ok |= 1;
  451.                ExtractAddress(value, &pe);
  452.                mail->From =  pe;
  453.             }
  454.             if (!stricmp(field, "reply-to"))
  455.             {
  456.                ok |= 8;
  457.                ExtractAddress(value, &pe);
  458.                mail->ReplyTo = pe;
  459.             }
  460.             if (!stricmp(field, "original-recipient"))
  461.             {
  462.                ExtractAddress(value, &pe);
  463.                email.OriginalRcpt = pe;
  464.             }
  465.             if (!stricmp(field, "disposition-notification-to"))
  466.             {
  467.                ExtractAddress(value, &pe);
  468.                email.ReceiptTo = pe;
  469.                email.ReceiptType = RCPT_TYPE_ALL;
  470.                mail->Flags |= MFLAG_SENDMDN;
  471.             }
  472.             if (!stricmp(field, "return-view-to"))
  473.             {
  474.                ExtractAddress(value, &pe);
  475.                email.ReceiptTo = pe;
  476.                email.ReceiptType = RCPT_TYPE_READ;
  477.             }
  478.             if (!stricmp(field, "return-receipt-to"))
  479.             {
  480.                email.RetRcpt = TRUE;
  481.             }
  482.             if (!stricmp(field, "to") && !(ok & 2))
  483.             {
  484.                ok |= 2;
  485.                if (p = MyStrChr(value, ',')) *p++ = 0;
  486.                ExtractAddress(value, &pe);
  487.                mail->To = pe;
  488.                if (p)
  489.                {
  490.                   mail->Flags |= MFLAG_MULTIRCPT;
  491.                   if (deep && !email.NoSTo) MA_GetRecipients(p, &(email.STo), &(email.NoSTo));
  492.                }
  493.             }
  494.             if (!stricmp(field, "cc"))
  495.             {
  496.                mail->Flags |= MFLAG_MULTIRCPT;
  497.                if (deep && !email.NoCC) MA_GetRecipients(value, &(email.CC), &(email.NoCC));
  498.             }
  499.             if (!stricmp(field, "bcc"))
  500.             {
  501.                mail->Flags |= MFLAG_MULTIRCPT;
  502.                if (deep && !email.NoBCC) MA_GetRecipients(value, &(email.BCC), &(email.NoBCC));
  503.             }
  504.             if (!stricmp(field, "subject"))
  505.             {
  506.                ok |= 4;
  507.                stccpy(mail->Subject, Trim(value), SIZE_SUBJECT);
  508.             }
  509.             if (!stricmp(field, "message-id"))
  510.             {
  511.                mail->cMsgID = CompressMsgID(p = Trim(value));
  512.                stccpy(email.MsgID, p, SIZE_MSGID);
  513.             }
  514.             if (!stricmp(field, "in-reply-to"))
  515.             {
  516.                mail->cIRTMsgID = CompressMsgID(p = Trim(value));
  517.                stccpy(email.IRTMsgID, p, SIZE_MSGID);
  518.             }
  519.             if (!stricmp(field, "date"))
  520.             {
  521.                foundDate = ScanDate(value);
  522.             }
  523.             if (!stricmp(field, "importance"))
  524.             {
  525.                p = Trim(value);
  526.                if (!stricmp(p, "high")) mail->Importance = 1;
  527.                if (!stricmp(p, "low")) mail->Importance = -1;
  528.             }
  529.             if (!stricmp(field, "priority") && !mail->Importance)
  530.             {
  531.                p = Trim(value);
  532.                if (!stricmp(p, "urgent")) mail->Importance = 1;
  533.                if (!stricmp(p, "non-urgent")) mail->Importance = -1;
  534.             }
  535.             if (!stricmp(field, "content-type"))
  536.             {
  537.                p = Trim(value);
  538.                if (!strnicmp(p, "multipart/mixed", 15)) mail->Flags |= MFLAG_MULTIPART;
  539.                if (!strnicmp(p, "multipart/report", 16)) mail->Flags |= MFLAG_REPORT;
  540.                if (!strnicmp(p, "multipart/encrypted", 19)) mail->Flags |= MFLAG_CRYPT;
  541.                if (!strnicmp(p, "multipart/signed", 16)) mail->Flags |= MFLAG_SIGNED;
  542.             }
  543.             if (!stricmp(field, "x-senderinfo"))
  544.             {
  545.                mail->Flags |= MFLAG_SENDERINFO;
  546.                if (deep) email.SenderInfo = StrBufCpy(email.SenderInfo, value);
  547.             }
  548.             if (deep)
  549.             {
  550.                if (!stricmp(field, "x-yam-options"))
  551.                {
  552.                   if (strstr(value, "delsent")) email.DelSend = TRUE;
  553.                   if (p = strstr(value, "sigfile")) email.Signature = p[7]-'0'+1;
  554.                   for (j = 1; j < 5; j++) if (strstr(value, SecCodes[j])) email.Security = j;
  555.                }
  556.                if (!strnicmp(field, "x-yam-header-", 13))
  557.                {
  558.                   email.Headers = StrBufCat(StrBufCat(email.Headers, &field[13]), ":");
  559.                   email.Headers = StrBufCat(StrBufCat(email.Headers, value), "\\n");
  560.                }
  561.             }
  562.          }
  563.       }
  564.       FreeData2D(&Header);
  565.       if ((ok & 8) && !mail->ReplyTo.RealName[0] && !stricmp(mail->ReplyTo.Address, mail->From.Address)) strcpy(mail->ReplyTo.RealName, mail->From.RealName);
  566.       mail->Date.ds_Days   = foundDate ? foundDate->ds_Days   : atol(mail->MailFile);
  567.       mail->Date.ds_Minute = foundDate ? foundDate->ds_Minute : 0;
  568.       mail->Date.ds_Tick   = foundDate ? foundDate->ds_Tick   : 0;
  569.       mail->Size = FileSize(fullfile);
  570.       if (statstr)
  571.          for (mail->Status = STATUS_NEW, i = 0; i < STATUS_NEW; i++)
  572.             if (*statstr == *Status[i]) mail->Status = i;
  573.       FinishUnpack(fullfile);
  574.       return &email;
  575.    }
  576.    FinishUnpack(fullfile);
  577.    return NULL;
  578. }
  579. ///
  580. /// MA_ScanMailBox
  581. //  Scans for message files in a folder directory
  582. void MA_ScanMailBox(struct Folder *folder)
  583. {
  584.    struct ExtendedMail *mail;
  585.    struct FileInfoBlock *fib;
  586.    BPTR lock;
  587.  
  588.    Busy(GetStr(MSG_BusyScanning), folder->Name, 0, 0);
  589.    ClearMailList(folder, TRUE);
  590.    fib = AllocDosObject(DOS_FIB,NULL);
  591.    if (lock = Lock(GetFolderDir(folder), ACCESS_READ))
  592.    {
  593.       Examine(lock, fib);
  594.       while (ExNext(lock,fib) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  595.       {
  596.          DoMethod(G->App,MUIM_Application_InputBuffered);
  597.          if (IsValidMailFile(fib->fib_FileName))
  598.             if (fib->fib_Size)
  599.             {
  600.                if (mail = MA_ExamineMail(folder,fib->fib_FileName,fib->fib_Comment,FALSE))
  601.                {
  602.                   AddMailToList((struct Mail *)mail, folder);
  603.                   MA_FreeEMailStruct(mail);
  604.                }
  605.             }
  606.             else
  607.             {
  608.                char path[SIZE_PATHFILE];
  609.                NameFromLock(lock, path, SIZE_PATHFILE);
  610.                AddPart(path, fib->fib_FileName, SIZE_PATHFILE);
  611.                DeleteFile(path);
  612.             }
  613.       }
  614.       UnLock(lock);
  615.    }
  616.    FreeDosObject(DOS_FIB,fib);
  617.    BusyEnd;
  618. }
  619. ///
  620.  
  621. /*** Hooks ***/
  622. /// PO_InitFolderList
  623. //  Creates a popup list of all folders
  624. SAVEDS ASM long PO_InitFolderList(REG(a2) Object *pop)
  625. {  
  626.    int i;
  627.    struct Folder **flist;
  628.  
  629.    DoMethod(pop, MUIM_List_Clear);
  630.    DoMethod(pop, MUIM_List_InsertSingle, GetStr(MSG_MA_Cancel), MUIV_List_Insert_Bottom);
  631.    if (flist = FO_CreateList())
  632.    {
  633.       for (i = 1; i <= (int)*flist; i++) if (flist[i]->Type != FT_SEPARATOR)
  634.          DoMethod(pop, MUIM_List_InsertSingle, flist[i]->Name, MUIV_List_Insert_Bottom);
  635.       free(flist);
  636.    }
  637.    return TRUE;
  638. }
  639. MakeHook(PO_InitFolderListHook, PO_InitFolderList);
  640. ///
  641. /// MA_LV_FDspFunc
  642. //  Folder listview display hook
  643. SAVEDS ASM long MA_LV_FDspFunc(REG(a2) char **array, REG(a1) struct Folder *entry)
  644. {
  645.    if (entry)
  646.    {
  647.       static char dispfold[SIZE_DEFAULT], disptot[SIZE_SMALL], dispunr[SIZE_SMALL], dispnew[SIZE_SMALL], dispsiz[SIZE_SMALL];
  648.       strcpy(array[0] = dispfold, entry->Name);
  649.       array[1] = array[2] = array[3] = array[4] = "";
  650.       *dispsiz = 0;
  651.       if (entry->Type == FT_SEPARATOR)
  652.          array[DISPLAY_ARRAY_MAX] = "\033E\033t\033c";
  653.       else
  654.       {
  655.          if (!*dispfold) sprintf(dispfold, "(%s)", FilePart(entry->Path));
  656.          if (entry->XPKType&1) strcat(dispfold, " \033o[0]");
  657.          if (entry->LoadedMode)
  658.          {
  659.             if (entry->New+entry->Unread) array[DISPLAY_ARRAY_MAX] = MUIX_PH;
  660.             sprintf(array[1] = disptot, "%d", entry->Total);
  661.             sprintf(array[2] = dispunr, "%d", entry->Unread);
  662.             sprintf(array[3] = dispnew, "%d", entry->New);
  663.             FormatSize(entry->Size, array[4] = dispsiz);
  664.          }
  665.       }
  666.    }
  667.    else 
  668.    {
  669.       array[0] = GetStr(MSG_Folder);
  670.       array[1] = GetStr(MSG_Total);
  671.       array[2] = GetStr(MSG_Unread);
  672.       array[3] = GetStr(MSG_New);
  673.       array[4] = GetStr(MSG_Size);
  674.    }
  675.    return 0;
  676. }
  677. MakeHook(MA_LV_FDspFuncHook,MA_LV_FDspFunc);
  678. ///
  679. /// MA_MakeFOFormat
  680. //  Creates format definition for folder listview
  681. void MA_MakeFOFormat(APTR lv)
  682. {
  683.    int i;
  684.    int defwidth[FOCOLNUM] = { -1,-1,-1,-1,-1 };
  685.    char format[SIZE_LARGE];
  686.    BOOL first = TRUE;
  687.    *format = 0;
  688.    for (i = 0; i < FOCOLNUM; i++) if (C->FolderCols & (1<<i))
  689.    {
  690.       if (first) first = FALSE; else strcat(format, " BAR,");
  691.       sprintf(&format[strlen(format)], "COL=%ld W=%ld", i, defwidth[i]);
  692.       if (i) strcat(format, " P=\033r");
  693.    }
  694.    strcat(format, " BAR");
  695.    set(lv, MUIA_NList_Format, format);
  696. }
  697. ///
  698.